JPA
,全名為Java Persistence API,是Sun 官方提出的Java 持久化規範,它為Java 開發人員提供了一種物件/關聯映射工具來管理Java 應用中的關係實體物件,它的出現主要是為了簡化現有的持久化開發工作和整合ORM 技術。
Spring Data JPA 是Spring 在ORM 框架、JPA 規範的基礎上封裝了一套JPA 應用框架,可使開發者用極簡的程式碼即可實現對資料庫的訪問和操作。
需要注意的是Spring Data JPA 新增與更新操作都是使用save()
方法進行,JPA
會透過主鍵去查詢是否存在,不存在就INSERT,存在就是UPDATE,其中,JPA
只能判斷INSERT 或是UPDATE,並不能判斷出是否更新部分欄位,所以沒有被賦值的欄位都會被覆蓋為NULL。
<!-- JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
spring.jpa.hibernate.ddl-auto
:
create
: 每次載入Hibernate 時,會刪除上次生成的資料表,再根據Model 類別重新生成資料表。
craete-drop
: 每次載入Hibernate 時都根據Model 類別生成資料表,但sessionFactory 一關閉就自動刪除資料表。
update
: 第一次載入Hibernate 時根據Model 類別生成資料表,之後載入Hibernate 時根據Model 類別更新資料表,即使資料表結構改變,但不會刪除以前的欄位。
要注意的是,當部署到伺服器後,不會馬上建立資料表,要等第一次應用時才會建立。
validate
: 每次載入Hibernate 時驗證建立資料表,只會和資料庫中的資料表進行比較,不會建立新的資料表,但會插入新值。
none
: 無動作。
spring.jpa.show-sql
: 是否在Console 顯示執行的SQL 語句。# JPA 設定
spring.jpa.hibernate.ddl-auto=update
# 顯示SQL 語句
spring.jpa.show-sql=true
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@SpringBootApplication
@EnableJpaAuditing
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}
@Entity
: 宣告為實體類。@Table
: 對應資料表名稱。@Id
: 設定為PRIMARY KEY。@GeneratedValue
: 設定該Column 生成方式。
GenerationType.AUTO
: 自動產生。GenerationType.IDENTITY
: 資料庫維護。@Column
: 對應資料表欄位名稱。package com.example.demo.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
@Entity
@Table(name = "member_account")
public class MemberAccount extends Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private String id;
@Column(name = "USERNAME", unique = true)
private String username;
@Column(name = "PASSWORD")
private String password;
@Column(name = "SALT")
private String salt;
}
@MappedSuperclass
: 宣告為實體類的父類別,它並不是完整的實體類,所以不會映射到資料表,但它的屬性會映射到它的子類別資料表中,可用於設定相同欄位。@EntityListeners(AuditingEntityListener.class)
: 監聽器,自動賦值創建時間、修改時間@CreateBy
: 設定為建立者,當實體被INSERT 時會預設值。@CreatedDate
: 設定為建立時間,當實體被INSERT 時會預設值。@Temporal(TemporalType.TIMESTAMP)
: 宣告該Column 儲存到資料表時的時間精度,該註解僅適用於被宣告為java.util.DATE 或java.util.Calendar 的屬性。
TemporalType.DATE
: 日期。TemporalType.TIME
: 時間。TemporalType.TIMESTAMP
: 日期和時間。@LastModifiedBy
: 設定為修改者,當實體被UPDATE 時會預設值。@LastModifiedDate
: 設定為修改時間,當實體被UPDATE 時會預設值。package com.example.demo.entity;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class Base {
@CreatedBy
@Column(name = "CREATE_BY")
private String create_by;
@CreatedDate
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "CREATE_TIME")
private Date create_time;
@LastModifiedBy
@Column(name = "UPDATE_BY")
private String update_by;
@LastModifiedDate
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "UPDATE_TIME")
private Date update_time;
}
package com.example.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.entity.MemberAccount;
public interface MemberAccountRepository extends JpaRepository<MemberAccount, Long> {
public MemberAccount findByUsername(String username);
}
package com.example.demo.repository;
import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.example.demo.entity.MemberAccount;
@SpringBootTest
public class MemberAccountRepositoryTest {
@Autowired
private MemberAccountRepository memberAccountRepository;
@Test
public void insert() {
MemberAccount memberAccount = new MemberAccount();
memberAccount.setUsername("username@email.com");
memberAccount.setPassword("password");
String salt = UUID.randomUUID().toString().toUpperCase().replaceAll("-", "");
memberAccount.setSalt(salt);
memberAccount.setCreate_by(memberAccount.getUsername());
memberAccount.setUpdate_by(memberAccount.getUsername());
memberAccountRepository.save(memberAccount);
System.out.println(memberAccount.getId());
}
@Test
public void findByUsername() {
String username = "username@email.com";
MemberAccount memberAccount = memberAccountRepository.findByUsername(username);
if(memberAccount != null) System.out.println(memberAccount.toString());
}
@Test
public void update() {
String username = "username@email.com";
MemberAccount memberAccount = memberAccountRepository.findByUsername(username);
memberAccount.setPassword("123456");
memberAccountRepository.save(memberAccount);
}
}
Java持久化API
Spring Data JPA
Spring Data JPA : Auditing with @CreatedBy, @CreatedDate, @LastModifiedBy and @LastModifiedDate